﻿using Server.Database;
using Server.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Server.Business
{
    public abstract class ExpressionHandler
    {
        protected ExpressionHandler Next { get; private set;}
        protected int FilterCount { get; private set; }
        protected ProdDB Source { get; private set; }

        protected ExpressionHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
        {
            Next = next;
            FilterCount = 5;
            Source = source;
        }

        public IList<ProdDB> Filter(IList<ProdDB> itemSource)
        {
            IList<ProdDB> list = InnerFilter(itemSource);

            if (ServerConfig.Singleton.Debug)
                LogService.Log(new LogDB() { Action = "推荐商品过滤操作", Info = list.Count.ToString() });

            if (list.Count > 0)
            {
                if (Next == null)
                    return list;
                else
                    return Next.Filter(list);
            }
            else
            {
                List<ProdDB> array = new List<ProdDB>();
                int index = 0;
                foreach (ProdDB item in itemSource)
                {
                    if (index++ <= FilterCount - 1)
                        array.Add(item);
                    else
                        break;
                }
                return array;
            }
        }

        protected abstract IList<ProdDB> InnerFilter(IList<ProdDB> list);

        protected int TryParseValue(string value)
        {
            if (string.IsNullOrEmpty(value))
                return 0;

            int intValue;
            int.TryParse(value, out intValue);
            return intValue;
        }
    }

    public class ClassHandler : ExpressionHandler
    {
        public ClassHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }

        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.ProdClass == Source.ProdClass
                    select r).ToList();
        }
    }

    public class PlaceHandler : ExpressionHandler
    {
        public PlaceHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }

        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.ProdPlace == Source.ProdPlace
                    select r).ToList();
        }
    }

    public class ExplainHandler : ExpressionHandler
    {
        public ExplainHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }

        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.OptExplain == Source.OptExplain
                    select r).ToList();
        }
    }

    public class AngleHandler : ExpressionHandler
    {
        public AngleHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }
        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            if (string.IsNullOrEmpty(Source.OptAngle))
            {
                return (from r in list
                        where string.IsNullOrEmpty(r.OptAngle)
                        select r).ToList();
            }
            else
            {
                int angle;
                int.TryParse(Source.OptAngle, out angle);
                if(angle > 0)
                {
                    if (angle <= 8)
                    {
                        return (from r in list
                                let value = TryParseValue(r.OptAngle)
                                where value > 0 && value <= 8
                                select r).ToList();
                    }
                    else if (angle >= 9 && angle <= 15)
                    {
                        return (from r in list
                                let value = TryParseValue(r.OptAngle)
                                where value >= 9 && value <= 15
                                select r).ToList();
                    }
                    else if (angle >= 16 && angle <= 25)
                    {
                        return (from r in list
                                let value = TryParseValue(r.OptAngle)
                                where value >= 16 && value <= 25
                                select r).ToList();
                    }
                    else if (angle >= 26 && angle <= 39)
                    {
                        return (from r in list
                                let value = TryParseValue(r.OptAngle)
                                where value >= 26 && value <= 39
                                select r).ToList();
                    }
                    else
                    {
                        return (from r in list
                                let value = TryParseValue(r.OptAngle)
                                where value >= 40
                                select r).ToList();
                    }
                }
                else
                {
                    return (from r in list
                            where r.OptAngle == Source.OptAngle
                            select r).ToList();
                }
            }
        }
    }


    public class ColorHandler : ExpressionHandler
    {
        public ColorHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }

        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            if (string.IsNullOrEmpty(Source.AdpColor))
            {
                return (from r in list
                        where string.IsNullOrEmpty(r.AdpColor)
                        select r).ToList();
            }
            else
            {

                int color;
                int.TryParse(Source.AdpColor, out color);
                if(color > 0)
                {
                    if (color < 3300)
                    {
                        return (from r in list
                                let value = TryParseValue(r.AdpColor)
                                where value > 0 && value < 3300
                                select r).ToList();
                    }
                    else if (color >= 3300 && color <= 5000)
                    {
                        return (from r in list
                               let value = TryParseValue(r.AdpColor)
                               where value >= 3300 && value <= 5000
                               select r).ToList();
                    }
                    else
                    {
                        return (from r in list
                               let value = TryParseValue(r.AdpColor)
                               where value > 5000
                               select r).ToList();
                    }
                }
                else
                {
                    return (from r in list
                            where r.AdpColor == Source.AdpColor
                            select r).ToList();
                }
            }
        }
    }

    public class OutputHandler : ExpressionHandler
    {
        public OutputHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }
        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.AdpOutput >= Source.AdpOutput * 0.9 
                        && r.AdpOutput <= Source.AdpOutput * 1.1
                    select r).ToList();
        }
    }

    public class PowerHandler : ExpressionHandler
    {
        public PowerHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }
        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.EleLgtPower >= Source.EleLgtPower * 0.9
                        && r.EleLgtPower <= Source.EleLgtPower * 1.1
                    select r).ToList();
        }
    }

    public class SetupHandler : ExpressionHandler
    {
        public SetupHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }

        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.ProjSetup == Source.ProjSetup
                    select r).ToList();
        }
    }

    public class DefendHandler : ExpressionHandler
    {
        public DefendHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }
        private int GetValue(string str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (char c in str)
            {
                if (Char.IsDigit(c))
                    sb.Append(c);
            }

            int value;
            int.TryParse(str, out value);
            return value;
        }

        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where GetValue(r.PhyDefend) >= GetValue(Source.PhyDefend)
                    select r).ToList();
        }
    }

    public class ShockHandler : ExpressionHandler
    {
        public ShockHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }
        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.EleShock == Source.EleShock
                    select r).ToList();
        }
    }

    public class VoltageHandler : ExpressionHandler
    {
        public VoltageHandler(ExpressionHandler next, ProdDB source, int filterCount = 5)
            : base(next, source, filterCount)
        {
        }
        protected override IList<ProdDB> InnerFilter(IList<ProdDB> list)
        {
            return (from r in list
                    where r.EleVoltage == Source.EleVoltage
                    select r).ToList();
        }
    }
}
